import time

from PyQt5.QtCore import QThread, pyqtSignal

import var


class FCFSWorker(QThread):
    current_time_signal = pyqtSignal(int)
    ready_signal = pyqtSignal(list)
    run_signal = pyqtSignal(list)
    finish_signal = pyqtSignal(list)

    output1_signal = pyqtSignal(str)

    def __init__(self, mission):
        super(FCFSWorker, self).__init__()
        self.jobs = mission.copy()
        self.ready_queue = []
        self.running_queue = []
        self.finished_queue = []
        self.current_time = 0
        self.time_slice = var.time_split

    def update_state(self):
        self.current_time_signal.emit(self.current_time)
        self.ready_signal.emit(self.ready_queue)
        self.run_signal.emit(self.running_queue)
        self.finish_signal.emit(self.finished_queue)

    def print_jobs(self):
        output_string = "作业ID\t到达时间\t运行时间\t开始时间\t结束时间\t周转时间\t带权周转时间\n"
        for job in self.finished_queue:
            output_string += str(job.id) + "\t" + str(job.arrival_time) + "\t" + str(job.burst_time) \
                             + "\t" + str(job.start_time) + "\t" + str(job.finish_time) + "\t" + str(
                job.turnaround_time) + "\t" + str(job.weighted_turnaround_time) + "\n"

        total_turnaround_time = sum([job.turnaround_time for job in self.finished_queue])
        total_weighted_turnaround_time = sum([job.weighted_turnaround_time for job in self.finished_queue])
        output_string += "\n"
        avg_around = total_turnaround_time / len(self.finished_queue)
        avg_weight_around = total_weighted_turnaround_time / len(self.finished_queue)
        output_string += f"平均周转时间: {avg_around}\n"
        output_string += f"平均带权周转时间: {avg_weight_around}\n"

        self.output1_signal.emit(output_string)

    def run(self):
        print("receive run")
        self.jobs.sort(key=lambda x: x.arrival_time)
        while self.jobs or self.running_queue or self.ready_queue:
            flag = 0
            for job in self.jobs:
                if job.arrival_time <= self.current_time:
                    self.ready_queue.append(job)
                    self.jobs.remove(job)

            if self.running_queue:
                current_job = self.running_queue[0]
                current_job.remaining_time -= self.time_slice

                if current_job.remaining_time <= 0:
                    current_job.finish_time = self.current_time
                    current_job.turnaround_time = current_job.finish_time - current_job.arrival_time
                    current_job.weighted_turnaround_time = current_job.turnaround_time / current_job.burst_time
                    self.finished_queue.append(current_job)
                    self.running_queue.pop(0)
                    flag = 1
            else:
                if self.ready_queue:
                    self.ready_queue.sort(key=lambda x: x.arrival_time)
                    running_job = self.ready_queue.pop(0)
                    running_job.start_time = self.current_time
                    self.running_queue.append(running_job)

            if flag == 0:
                self.current_time += self.time_slice
                self.update_state()
                time.sleep(self.time_slice)
        self.print_jobs()

        print("finish")
